/*
 * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package java.awt;

import java.awt.peer.DialogPeer;
import java.awt.event.*;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicLong;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.accessibility.*;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import sun.awt.PeerEvent;
import sun.awt.util.IdentityArrayList;
import sun.awt.util.IdentityLinkedList;
import sun.security.util.SecurityConstants;
import java.security.AccessControlException;

/**
 * A Dialog is a top-level window with a title and a border
 * that is typically used to take some form of input from the user.
 *
 * The size of the dialog includes any area designated for the
 * border.  The dimensions of the border area can be obtained
 * using the <code>getInsets</code> method, however, since
 * these dimensions are platform-dependent, a valid insets
 * value cannot be obtained until the dialog is made displayable
 * by either calling <code>pack</code> or <code>show</code>.
 * Since the border area is included in the overall size of the
 * dialog, the border effectively obscures a portion of the dialog,
 * constraining the area available for rendering and/or displaying
 * subcomponents to the rectangle which has an upper-left corner
 * location of <code>(insets.left, insets.top)</code>, and has a size of
 * <code>width - (insets.left + insets.right)</code> by
 * <code>height - (insets.top + insets.bottom)</code>.
 * <p>
 * The default layout for a dialog is <code>BorderLayout</code>.
 * <p>
 * A dialog may have its native decorations (i.e. Frame &amp; Titlebar) turned off
 * with <code>setUndecorated</code>.  This can only be done while the dialog
 * is not {@link Component#isDisplayable() displayable}.
 * <p>
 * A dialog may have another window as its owner when it's constructed.  When
 * the owner window of a visible dialog is minimized, the dialog will
 * automatically be hidden from the user. When the owner window is subsequently
 * restored, the dialog is made visible to the user again.
 * <p>
 * In a multi-screen environment, you can create a <code>Dialog</code>
 * on a different screen device than its owner.  See {@link java.awt.Frame} for
 * more information.
 * <p>
 * A dialog can be either modeless (the default) or modal.  A modal
 * dialog is one which blocks input to some other top-level windows
 * in the application, except for any windows created with the dialog
 * as their owner. See <a href="doc-files/Modality.html">AWT Modality</a>
 * specification for details.
 * <p>
 * Dialogs are capable of generating the following
 * <code>WindowEvents</code>:
 * <code>WindowOpened</code>, <code>WindowClosing</code>,
 * <code>WindowClosed</code>, <code>WindowActivated</code>,
 * <code>WindowDeactivated</code>, <code>WindowGainedFocus</code>,
 * <code>WindowLostFocus</code>.
 *
 * @author Sami Shaio
 * @author Arthur van Hoff
 * @see WindowEvent
 * @see Window#addWindowListener
 * @since JDK1.0
 */
public class Dialog extends Window {

  static {
        /* ensure that the necessary native libraries are loaded */
    Toolkit.loadLibraries();
    if (!GraphicsEnvironment.isHeadless()) {
      initIDs();
    }
  }

  /**
   * A dialog's resizable property. Will be true
   * if the Dialog is to be resizable, otherwise
   * it will be false.
   *
   * @serial
   * @see #setResizable(boolean)
   */
  boolean resizable = true;


  /**
   * This field indicates whether the dialog is undecorated.
   * This property can only be changed while the dialog is not displayable.
   * <code>undecorated</code> will be true if the dialog is
   * undecorated, otherwise it will be false.
   *
   * @serial
   * @see #setUndecorated(boolean)
   * @see #isUndecorated()
   * @see Component#isDisplayable()
   * @since 1.4
   */
  boolean undecorated = false;

  private transient boolean initialized = false;

  /**
   * Modal dialogs block all input to some top-level windows.
   * Whether a particular window is blocked depends on dialog's type
   * of modality; this is called the "scope of blocking". The
   * <code>ModalityType</code> enum specifies modal types and their
   * associated scopes.
   *
   * @see Dialog#getModalityType
   * @see Dialog#setModalityType
   * @see Toolkit#isModalityTypeSupported
   * @since 1.6
   */
  public static enum ModalityType {
    /**
     * <code>MODELESS</code> dialog doesn't block any top-level windows.
     */
    MODELESS,
    /**
     * A <code>DOCUMENT_MODAL</code> dialog blocks input to all top-level windows
     * from the same document except those from its own child hierarchy.
     * A document is a top-level window without an owner. It may contain child
     * windows that, together with the top-level window are treated as a single
     * solid document. Since every top-level window must belong to some
     * document, its root can be found as the top-nearest window without an owner.
     */
    DOCUMENT_MODAL,
    /**
     * An <code>APPLICATION_MODAL</code> dialog blocks all top-level windows
     * from the same Java application except those from its own child hierarchy.
     * If there are several applets launched in a browser, they can be
     * treated either as separate applications or a single one. This behavior
     * is implementation-dependent.
     */
    APPLICATION_MODAL,
    /**
     * A <code>TOOLKIT_MODAL</code> dialog blocks all top-level windows run
     * from the same toolkit except those from its own child hierarchy. If there
     * are several applets launched in a browser, all of them run with the same
     * toolkit; thus, a toolkit-modal dialog displayed by an applet may affect
     * other applets and all windows of the browser instance which embeds the
     * Java runtime environment for this toolkit.
     * Special <code>AWTPermission</code> "toolkitModality" must be granted to use
     * toolkit-modal dialogs. If a <code>TOOLKIT_MODAL</code> dialog is being created
     * and this permission is not granted, a <code>SecurityException</code> will be
     * thrown, and no dialog will be created. If a modality type is being changed
     * to <code>TOOLKIT_MODAL</code> and this permission is not granted, a
     * <code>SecurityException</code> will be thrown, and the modality type will
     * be left unchanged.
     */
    TOOLKIT_MODAL
  }

  ;

  /**
   * Default modality type for modal dialogs. The default modality type is
   * <code>APPLICATION_MODAL</code>. Calling the oldstyle <code>setModal(true)</code>
   * is equal to <code>setModalityType(DEFAULT_MODALITY_TYPE)</code>.
   *
   * @see java.awt.Dialog.ModalityType
   * @see java.awt.Dialog#setModal
   * @since 1.6
   */
  public final static ModalityType DEFAULT_MODALITY_TYPE = ModalityType.APPLICATION_MODAL;

  /**
   * True if this dialog is modal, false is the dialog is modeless.
   * A modal dialog blocks user input to some application top-level
   * windows. This field is kept only for backwards compatibility. Use the
   * {@link Dialog.ModalityType ModalityType} enum instead.
   *
   * @serial
   * @see #isModal
   * @see #setModal
   * @see #getModalityType
   * @see #setModalityType
   * @see ModalityType
   * @see ModalityType#MODELESS
   * @see #DEFAULT_MODALITY_TYPE
   */
  boolean modal;

  /**
   * Modality type of this dialog. If the dialog's modality type is not
   * {@link Dialog.ModalityType#MODELESS ModalityType.MODELESS}, it blocks all
   * user input to some application top-level windows.
   *
   * @serial
   * @see ModalityType
   * @see #getModalityType
   * @see #setModalityType
   * @since 1.6
   */
  ModalityType modalityType;

  /**
   * Any top-level window can be marked not to be blocked by modal
   * dialogs. This is called "modal exclusion". This enum specifies
   * the possible modal exclusion types.
   *
   * @see Window#getModalExclusionType
   * @see Window#setModalExclusionType
   * @see Toolkit#isModalExclusionTypeSupported
   * @since 1.6
   */
  public static enum ModalExclusionType {
    /**
     * No modal exclusion.
     */
    NO_EXCLUDE,
    /**
     * <code>APPLICATION_EXCLUDE</code> indicates that a top-level window
     * won't be blocked by any application-modal dialogs. Also, it isn't
     * blocked by document-modal dialogs from outside of its child hierarchy.
     */
    APPLICATION_EXCLUDE,
    /**
     * <code>TOOLKIT_EXCLUDE</code> indicates that a top-level window
     * won't be blocked by  application-modal or toolkit-modal dialogs. Also,
     * it isn't blocked by document-modal dialogs from outside of its
     * child hierarchy.
     * The "toolkitModality" <code>AWTPermission</code> must be granted
     * for this exclusion. If an exclusion property is being changed to
     * <code>TOOLKIT_EXCLUDE</code> and this permission is not granted, a
     * <code>SecurityEcxeption</code> will be thrown, and the exclusion
     * property will be left unchanged.
     */
    TOOLKIT_EXCLUDE
  }

  ;

  /* operations with this list should be synchronized on tree lock*/
  transient static IdentityArrayList<Dialog> modalDialogs = new IdentityArrayList<Dialog>();

  transient IdentityArrayList<Window> blockedWindows = new IdentityArrayList<Window>();

  /**
   * Specifies the title of the Dialog.
   * This field can be null.
   *
   * @serial
   * @see #getTitle()
   * @see #setTitle(String)
   */
  String title;

  private transient ModalEventFilter modalFilter;
  private transient volatile SecondaryLoop secondaryLoop;

  /*
   * Indicates that this dialog is being hidden. This flag is set to true at
   * the beginning of hide() and to false at the end of hide().
   *
   * @see #hide()
   * @see #hideAndDisposePreHandler()
   * @see #hideAndDisposeHandler()
   * @see #shouldBlock()
   */
  transient volatile boolean isInHide = false;

  /*
   * Indicates that this dialog is being disposed. This flag is set to true at
   * the beginning of doDispose() and to false at the end of doDispose().
   *
   * @see #hide()
   * @see #hideAndDisposePreHandler()
   * @see #hideAndDisposeHandler()
   * @see #doDispose()
   */
  transient volatile boolean isInDispose = false;

  private static final String base = "dialog";
  private static int nameCounter = 0;

  /*
   * JDK 1.1 serialVersionUID
   */
  private static final long serialVersionUID = 5920926903803293709L;

  /**
   * Constructs an initially invisible, modeless <code>Dialog</code> with
   * the specified owner <code>Frame</code> and an empty title.
   *
   * @param owner the owner of the dialog or <code>null</code> if this dialog has no owner
   * @throws java.lang.IllegalArgumentException if the <code>owner</code>'s
   * <code>GraphicsConfiguration</code> is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @see Component#setSize
   * @see Component#setVisible
   */
  public Dialog(Frame owner) {
    this(owner, "", false);
  }

  /**
   * Constructs an initially invisible <code>Dialog</code> with the specified
   * owner <code>Frame</code> and modality and an empty title.
   *
   * @param owner the owner of the dialog or <code>null</code> if this dialog has no owner
   * @param modal specifies whether dialog blocks user input to other top-level windows when shown.
   * If <code>false</code>, the dialog is <code>MODELESS</code>; if <code>true</code>, the modality
   * type property is set to <code>DEFAULT_MODALITY_TYPE</code>
   * @throws java.lang.IllegalArgumentException if the <code>owner</code>'s
   * <code>GraphicsConfiguration</code> is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @see java.awt.Dialog.ModalityType
   * @see java.awt.Dialog.ModalityType#MODELESS
   * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE
   * @see java.awt.Dialog#setModal
   * @see java.awt.Dialog#setModalityType
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public Dialog(Frame owner, boolean modal) {
    this(owner, "", modal);
  }

  /**
   * Constructs an initially invisible, modeless <code>Dialog</code> with
   * the specified owner <code>Frame</code> and title.
   *
   * @param owner the owner of the dialog or <code>null</code> if this dialog has no owner
   * @param title the title of the dialog or <code>null</code> if this dialog has no title
   * @throws IllegalArgumentException if the <code>owner</code>'s <code>GraphicsConfiguration</code>
   * is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @see Component#setSize
   * @see Component#setVisible
   */
  public Dialog(Frame owner, String title) {
    this(owner, title, false);
  }

  /**
   * Constructs an initially invisible <code>Dialog</code> with the
   * specified owner <code>Frame</code>, title and modality.
   *
   * @param owner the owner of the dialog or <code>null</code> if this dialog has no owner
   * @param title the title of the dialog or <code>null</code> if this dialog has no title
   * @param modal specifies whether dialog blocks user input to other top-level windows when shown.
   * If <code>false</code>, the dialog is <code>MODELESS</code>; if <code>true</code>, the modality
   * type property is set to <code>DEFAULT_MODALITY_TYPE</code>
   * @throws java.lang.IllegalArgumentException if the <code>owner</code>'s
   * <code>GraphicsConfiguration</code> is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @see java.awt.Dialog.ModalityType
   * @see java.awt.Dialog.ModalityType#MODELESS
   * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE
   * @see java.awt.Dialog#setModal
   * @see java.awt.Dialog#setModalityType
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @see Component#setSize
   * @see Component#setVisible
   */
  public Dialog(Frame owner, String title, boolean modal) {
    this(owner, title, modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS);
  }

  /**
   * Constructs an initially invisible <code>Dialog</code> with the specified owner
   * <code>Frame</code>, title, modality, and <code>GraphicsConfiguration</code>.
   *
   * @param owner the owner of the dialog or <code>null</code> if this dialog has no owner
   * @param title the title of the dialog or <code>null</code> if this dialog has no title
   * @param modal specifies whether dialog blocks user input to other top-level windows when shown.
   * If <code>false</code>, the dialog is <code>MODELESS</code>; if <code>true</code>, the modality
   * type property is set to <code>DEFAULT_MODALITY_TYPE</code>
   * @param gc the <code>GraphicsConfiguration</code> of the target screen device; if
   * <code>null</code>, the default system <code>GraphicsConfiguration</code> is assumed
   * @throws java.lang.IllegalArgumentException if <code>gc</code> is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @see java.awt.Dialog.ModalityType
   * @see java.awt.Dialog.ModalityType#MODELESS
   * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE
   * @see java.awt.Dialog#setModal
   * @see java.awt.Dialog#setModalityType
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @see Component#setSize
   * @see Component#setVisible
   * @since 1.4
   */
  public Dialog(Frame owner, String title, boolean modal,
      GraphicsConfiguration gc) {
    this(owner, title, modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS, gc);
  }

  /**
   * Constructs an initially invisible, modeless <code>Dialog</code> with
   * the specified owner <code>Dialog</code> and an empty title.
   *
   * @param owner the owner of the dialog or <code>null</code> if this dialog has no owner
   * @throws java.lang.IllegalArgumentException if the <code>owner</code>'s
   * <code>GraphicsConfiguration</code> is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @since 1.2
   */
  public Dialog(Dialog owner) {
    this(owner, "", false);
  }

  /**
   * Constructs an initially invisible, modeless <code>Dialog</code>
   * with the specified owner <code>Dialog</code> and title.
   *
   * @param owner the owner of the dialog or <code>null</code> if this has no owner
   * @param title the title of the dialog or <code>null</code> if this dialog has no title
   * @throws java.lang.IllegalArgumentException if the <code>owner</code>'s
   * <code>GraphicsConfiguration</code> is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @since 1.2
   */
  public Dialog(Dialog owner, String title) {
    this(owner, title, false);
  }

  /**
   * Constructs an initially invisible <code>Dialog</code> with the
   * specified owner <code>Dialog</code>, title, and modality.
   *
   * @param owner the owner of the dialog or <code>null</code> if this dialog has no owner
   * @param title the title of the dialog or <code>null</code> if this dialog has no title
   * @param modal specifies whether dialog blocks user input to other top-level windows when shown.
   * If <code>false</code>, the dialog is <code>MODELESS</code>; if <code>true</code>, the modality
   * type property is set to <code>DEFAULT_MODALITY_TYPE</code>
   * @throws IllegalArgumentException if the <code>owner</code>'s <code>GraphicsConfiguration</code>
   * is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @see java.awt.Dialog.ModalityType
   * @see java.awt.Dialog.ModalityType#MODELESS
   * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE
   * @see java.awt.Dialog#setModal
   * @see java.awt.Dialog#setModalityType
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @since 1.2
   */
  public Dialog(Dialog owner, String title, boolean modal) {
    this(owner, title, modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS);
  }

  /**
   * Constructs an initially invisible <code>Dialog</code> with the
   * specified owner <code>Dialog</code>, title, modality and
   * <code>GraphicsConfiguration</code>.
   *
   * @param owner the owner of the dialog or <code>null</code> if this dialog has no owner
   * @param title the title of the dialog or <code>null</code> if this dialog has no title
   * @param modal specifies whether dialog blocks user input to other top-level windows when shown.
   * If <code>false</code>, the dialog is <code>MODELESS</code>; if <code>true</code>, the modality
   * type property is set to <code>DEFAULT_MODALITY_TYPE</code>
   * @param gc the <code>GraphicsConfiguration</code> of the target screen device; if
   * <code>null</code>, the default system <code>GraphicsConfiguration</code> is assumed
   * @throws java.lang.IllegalArgumentException if <code>gc</code> is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @see java.awt.Dialog.ModalityType
   * @see java.awt.Dialog.ModalityType#MODELESS
   * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE
   * @see java.awt.Dialog#setModal
   * @see java.awt.Dialog#setModalityType
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @see Component#setSize
   * @see Component#setVisible
   * @since 1.4
   */
  public Dialog(Dialog owner, String title, boolean modal,
      GraphicsConfiguration gc) {
    this(owner, title, modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS, gc);
  }

  /**
   * Constructs an initially invisible, modeless <code>Dialog</code> with the
   * specified owner <code>Window</code> and an empty title.
   *
   * @param owner the owner of the dialog. The owner must be an instance of {@link java.awt.Dialog
   * Dialog}, {@link java.awt.Frame Frame}, any of their descendents or <code>null</code>
   * @throws java.lang.IllegalArgumentException if the <code>owner</code> is not an instance of
   * {@link java.awt.Dialog Dialog} or {@link java.awt.Frame Frame}
   * @throws java.lang.IllegalArgumentException if the <code>owner</code>'s
   * <code>GraphicsConfiguration</code> is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @since 1.6
   */
  public Dialog(Window owner) {
    this(owner, "", ModalityType.MODELESS);
  }

  /**
   * Constructs an initially invisible, modeless <code>Dialog</code> with
   * the specified owner <code>Window</code> and title.
   *
   * @param owner the owner of the dialog. The owner must be an instance of {@link java.awt.Dialog
   * Dialog}, {@link java.awt.Frame Frame}, any of their descendents or <code>null</code>
   * @param title the title of the dialog or <code>null</code> if this dialog has no title
   * @throws java.lang.IllegalArgumentException if the <code>owner</code> is not an instance of
   * {@link java.awt.Dialog Dialog} or {@link java.awt.Frame Frame}
   * @throws java.lang.IllegalArgumentException if the <code>owner</code>'s
   * <code>GraphicsConfiguration</code> is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @since 1.6
   */
  public Dialog(Window owner, String title) {
    this(owner, title, ModalityType.MODELESS);
  }

  /**
   * Constructs an initially invisible <code>Dialog</code> with the
   * specified owner <code>Window</code> and modality and an empty title.
   *
   * @param owner the owner of the dialog. The owner must be an instance of {@link java.awt.Dialog
   * Dialog}, {@link java.awt.Frame Frame}, any of their descendents or <code>null</code>
   * @param modalityType specifies whether dialog blocks input to other windows when shown.
   * <code>null</code> value and unsupported modality types are equivalent to <code>MODELESS</code>
   * @throws java.lang.IllegalArgumentException if the <code>owner</code> is not an instance of
   * {@link java.awt.Dialog Dialog} or {@link java.awt.Frame Frame}
   * @throws java.lang.IllegalArgumentException if the <code>owner</code>'s
   * <code>GraphicsConfiguration</code> is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @throws SecurityException if the calling thread does not have permission to create modal
   * dialogs with the given <code>modalityType</code>
   * @see java.awt.Dialog.ModalityType
   * @see java.awt.Dialog#setModal
   * @see java.awt.Dialog#setModalityType
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @see java.awt.Toolkit#isModalityTypeSupported
   * @since 1.6
   */
  public Dialog(Window owner, ModalityType modalityType) {
    this(owner, "", modalityType);
  }

  /**
   * Constructs an initially invisible <code>Dialog</code> with the
   * specified owner <code>Window</code>, title and modality.
   *
   * @param owner the owner of the dialog. The owner must be an instance of {@link java.awt.Dialog
   * Dialog}, {@link java.awt.Frame Frame}, any of their descendents or <code>null</code>
   * @param title the title of the dialog or <code>null</code> if this dialog has no title
   * @param modalityType specifies whether dialog blocks input to other windows when shown.
   * <code>null</code> value and unsupported modality types are equivalent to <code>MODELESS</code>
   * @throws java.lang.IllegalArgumentException if the <code>owner</code> is not an instance of
   * {@link java.awt.Dialog Dialog} or {@link java.awt.Frame Frame}
   * @throws java.lang.IllegalArgumentException if the <code>owner</code>'s
   * <code>GraphicsConfiguration</code> is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @throws SecurityException if the calling thread does not have permission to create modal
   * dialogs with the given <code>modalityType</code>
   * @see java.awt.Dialog.ModalityType
   * @see java.awt.Dialog#setModal
   * @see java.awt.Dialog#setModalityType
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @see java.awt.Toolkit#isModalityTypeSupported
   * @since 1.6
   */
  public Dialog(Window owner, String title, ModalityType modalityType) {
    super(owner);

    if ((owner != null) &&
        !(owner instanceof Frame) &&
        !(owner instanceof Dialog)) {
      throw new IllegalArgumentException("Wrong parent window");
    }

    this.title = title;
    setModalityType(modalityType);
    SunToolkit.checkAndSetPolicy(this);
    initialized = true;
  }

  /**
   * Constructs an initially invisible <code>Dialog</code> with the
   * specified owner <code>Window</code>, title, modality and
   * <code>GraphicsConfiguration</code>.
   *
   * @param owner the owner of the dialog. The owner must be an instance of {@link java.awt.Dialog
   * Dialog}, {@link java.awt.Frame Frame}, any of their descendents or <code>null</code>
   * @param title the title of the dialog or <code>null</code> if this dialog has no title
   * @param modalityType specifies whether dialog blocks input to other windows when shown.
   * <code>null</code> value and unsupported modality types are equivalent to <code>MODELESS</code>
   * @param gc the <code>GraphicsConfiguration</code> of the target screen device; if
   * <code>null</code>, the default system <code>GraphicsConfiguration</code> is assumed
   * @throws java.lang.IllegalArgumentException if the <code>owner</code> is not an instance of
   * {@link java.awt.Dialog Dialog} or {@link java.awt.Frame Frame}
   * @throws java.lang.IllegalArgumentException if <code>gc</code> is not from a screen device
   * @throws HeadlessException when <code>GraphicsEnvironment.isHeadless()</code> returns
   * <code>true</code>
   * @throws SecurityException if the calling thread does not have permission to create modal
   * dialogs with the given <code>modalityType</code>
   * @see java.awt.Dialog.ModalityType
   * @see java.awt.Dialog#setModal
   * @see java.awt.Dialog#setModalityType
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @see java.awt.Toolkit#isModalityTypeSupported
   * @since 1.6
   */
  public Dialog(Window owner, String title, ModalityType modalityType,
      GraphicsConfiguration gc) {
    super(owner, gc);

    if ((owner != null) &&
        !(owner instanceof Frame) &&
        !(owner instanceof Dialog)) {
      throw new IllegalArgumentException("wrong owner window");
    }

    this.title = title;
    setModalityType(modalityType);
    SunToolkit.checkAndSetPolicy(this);
    initialized = true;
  }

  /**
   * Construct a name for this component.  Called by getName() when the
   * name is null.
   */
  String constructComponentName() {
    synchronized (Dialog.class) {
      return base + nameCounter++;
    }
  }

  /**
   * Makes this Dialog displayable by connecting it to
   * a native screen resource.  Making a dialog displayable will
   * cause any of its children to be made displayable.
   * This method is called internally by the toolkit and should
   * not be called directly by programs.
   *
   * @see Component#isDisplayable
   * @see #removeNotify
   */
  public void addNotify() {
    synchronized (getTreeLock()) {
      if (parent != null && parent.getPeer() == null) {
        parent.addNotify();
      }

      if (peer == null) {
        peer = getToolkit().createDialog(this);
      }
      super.addNotify();
    }
  }

  /**
   * Indicates whether the dialog is modal.
   * <p>
   * This method is obsolete and is kept for backwards compatibility only.
   * Use {@link #getModalityType getModalityType()} instead.
   *
   * @return <code>true</code> if this dialog window is modal; <code>false</code> otherwise
   * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE
   * @see java.awt.Dialog.ModalityType#MODELESS
   * @see java.awt.Dialog#setModal
   * @see java.awt.Dialog#getModalityType
   * @see java.awt.Dialog#setModalityType
   */
  public boolean isModal() {
    return isModal_NoClientCode();
  }

  final boolean isModal_NoClientCode() {
    return modalityType != ModalityType.MODELESS;
  }

  /**
   * Specifies whether this dialog should be modal.
   * <p>
   * This method is obsolete and is kept for backwards compatibility only.
   * Use {@link #setModalityType setModalityType()} instead.
   * <p>
   * Note: changing modality of the visible dialog may have no effect
   * until it is hidden and then shown again.
   *
   * @param modal specifies whether dialog blocks input to other windows when shown; calling to
   * <code>setModal(true)</code> is equivalent to <code>setModalityType(Dialog.DEFAULT_MODALITY_TYPE)</code>,
   * and calling to <code>setModal(false)</code> is equvivalent to <code>setModalityType(Dialog.ModalityType.MODELESS)</code>
   * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE
   * @see java.awt.Dialog.ModalityType#MODELESS
   * @see java.awt.Dialog#isModal
   * @see java.awt.Dialog#getModalityType
   * @see java.awt.Dialog#setModalityType
   * @since 1.1
   */
  public void setModal(boolean modal) {
    this.modal = modal;
    setModalityType(modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS);
  }

  /**
   * Returns the modality type of this dialog.
   *
   * @return modality type of this dialog
   * @see java.awt.Dialog#setModalityType
   * @since 1.6
   */
  public ModalityType getModalityType() {
    return modalityType;
  }

  /**
   * Sets the modality type for this dialog. See {@link
   * java.awt.Dialog.ModalityType ModalityType} for possible modality types.
   * <p>
   * If the given modality type is not supported, <code>MODELESS</code>
   * is used. You may want to call <code>getModalityType()</code> after calling
   * this method to ensure that the modality type has been set.
   * <p>
   * Note: changing modality of the visible dialog may have no effect
   * until it is hidden and then shown again.
   *
   * @param type specifies whether dialog blocks input to other windows when shown.
   * <code>null</code> value and unsupported modality types are equivalent to <code>MODELESS</code>
   * @throws SecurityException if the calling thread does not have permission to create modal
   * dialogs with the given <code>modalityType</code>
   * @see java.awt.Dialog#getModalityType
   * @see java.awt.Toolkit#isModalityTypeSupported
   * @since 1.6
   */
  public void setModalityType(ModalityType type) {
    if (type == null) {
      type = Dialog.ModalityType.MODELESS;
    }
    if (!Toolkit.getDefaultToolkit().isModalityTypeSupported(type)) {
      type = Dialog.ModalityType.MODELESS;
    }
    if (modalityType == type) {
      return;
    }

    checkModalityPermission(type);

    modalityType = type;
    modal = (modalityType != ModalityType.MODELESS);
  }

  /**
   * Gets the title of the dialog. The title is displayed in the
   * dialog's border.
   *
   * @return the title of this dialog window. The title may be <code>null</code>.
   * @see java.awt.Dialog#setTitle
   */
  public String getTitle() {
    return title;
  }

  /**
   * Sets the title of the Dialog.
   *
   * @param title the title displayed in the dialog's border; a null value results in an empty
   * title
   * @see #getTitle
   */
  public void setTitle(String title) {
    String oldTitle = this.title;

    synchronized (this) {
      this.title = title;
      DialogPeer peer = (DialogPeer) this.peer;
      if (peer != null) {
        peer.setTitle(title);
      }
    }
    firePropertyChange("title", oldTitle, title);
  }

  /**
   * @return true if we actually showed, false if we just called toFront()
   */
  private boolean conditionalShow(Component toFocus, AtomicLong time) {
    boolean retval;

    closeSplashScreen();

    synchronized (getTreeLock()) {
      if (peer == null) {
        addNotify();
      }
      validateUnconditionally();
      if (visible) {
        toFront();
        retval = false;
      } else {
        visible = retval = true;

        // check if this dialog should be modal blocked BEFORE calling peer.show(),
        // otherwise, a pair of FOCUS_GAINED and FOCUS_LOST may be mistakenly
        // generated for the dialog
        if (!isModal()) {
          checkShouldBeBlocked(this);
        } else {
          modalDialogs.add(this);
          modalShow();
        }

        if (toFocus != null && time != null && isFocusable() &&
            isEnabled() && !isModalBlocked()) {
          // keep the KeyEvents from being dispatched
          // until the focus has been transfered
          time.set(Toolkit.getEventQueue().getMostRecentKeyEventTime());
          KeyboardFocusManager.getCurrentKeyboardFocusManager().
              enqueueKeyEvents(time.get(), toFocus);
        }

        // This call is required as the show() method of the Dialog class
        // does not invoke the super.show(). So wried... :(
        mixOnShowing();

        peer.setVisible(true); // now guaranteed never to block
        if (isModalBlocked()) {
          modalBlocker.toFront();
        }

        setLocationByPlatform(false);
        for (int i = 0; i < ownedWindowList.size(); i++) {
          Window child = ownedWindowList.elementAt(i).get();
          if ((child != null) && child.showWithParent) {
            child.show();
            child.showWithParent = false;
          }       // endif
        }   // endfor
        Window.updateChildFocusableWindowState(this);

        createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
            this, parent,
            HierarchyEvent.SHOWING_CHANGED,
            Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
        if (componentListener != null ||
            (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 ||
            Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) {
          ComponentEvent e =
              new ComponentEvent(this, ComponentEvent.COMPONENT_SHOWN);
          Toolkit.getEventQueue().postEvent(e);
        }
      }
    }

    if (retval && (state & OPENED) == 0) {
      postWindowEvent(WindowEvent.WINDOW_OPENED);
      state |= OPENED;
    }

    return retval;
  }

  /**
   * Shows or hides this {@code Dialog} depending on the value of parameter
   * {@code b}.
   *
   * @param b if {@code true}, makes the {@code Dialog} visible, otherwise hides the {@code Dialog}.
   * If the dialog and/or its owner are not yet displayable, both are made displayable.  The dialog
   * will be validated prior to being made visible. If {@code false}, hides the {@code Dialog} and
   * then causes {@code setVisible(true)} to return if it is currently blocked. <p> <b>Notes for
   * modal dialogs</b>. <ul> <li>{@code setVisible(true)}:  If the dialog is not already visible,
   * this call will not return until the dialog is hidden by calling {@code setVisible(false)} or
   * {@code dispose}. <li>{@code setVisible(false)}:  Hides the dialog and then returns on {@code
   * setVisible(true)} if it is currently blocked. <li>It is OK to call this method from the event
   * dispatching thread because the toolkit ensures that other events are not blocked while this
   * method is blocked. </ul>
   * @see java.awt.Window#setVisible
   * @see java.awt.Window#dispose
   * @see java.awt.Component#isDisplayable
   * @see java.awt.Component#validate
   * @see java.awt.Dialog#isModal
   */
  public void setVisible(boolean b) {
    super.setVisible(b);
  }

  /**
   * Makes the {@code Dialog} visible. If the dialog and/or its owner
   * are not yet displayable, both are made displayable.  The
   * dialog will be validated prior to being made visible.
   * If the dialog is already visible, this will bring the dialog
   * to the front.
   * <p>
   * If the dialog is modal and is not already visible, this call
   * will not return until the dialog is hidden by calling hide or
   * dispose. It is permissible to show modal dialogs from the event
   * dispatching thread because the toolkit will ensure that another
   * event pump runs while the one which invoked this method is blocked.
   *
   * @see Component#hide
   * @see Component#isDisplayable
   * @see Component#validate
   * @see #isModal
   * @see Window#setVisible(boolean)
   * @deprecated As of JDK version 1.5, replaced by {@link #setVisible(boolean)
   * setVisible(boolean)}.
   */
  @Deprecated
  public void show() {
    if (!initialized) {
      throw new IllegalStateException("The dialog component " +
          "has not been initialized properly");
    }

    beforeFirstShow = false;
    if (!isModal()) {
      conditionalShow(null, null);
    } else {
      AppContext showAppContext = AppContext.getAppContext();

      AtomicLong time = new AtomicLong();
      Component predictedFocusOwner = null;
      try {
        predictedFocusOwner = getMostRecentFocusOwner();
        if (conditionalShow(predictedFocusOwner, time)) {
          modalFilter = ModalEventFilter.createFilterForDialog(this);
          final Conditional cond = new Conditional() {
            @Override
            public boolean evaluate() {
              return windowClosingException == null;
            }
          };

          // if this dialog is toolkit-modal, the filter should be added
          // to all EDTs (for all AppContexts)
          if (modalityType == ModalityType.TOOLKIT_MODAL) {
            Iterator<AppContext> it = AppContext.getAppContexts().iterator();
            while (it.hasNext()) {
              AppContext appContext = it.next();
              if (appContext == showAppContext) {
                continue;
              }
              EventQueue eventQueue = (EventQueue) appContext.get(AppContext.EVENT_QUEUE_KEY);
              // it may occur that EDT for appContext hasn't been started yet, so
              // we post an empty invocation event to trigger EDT initialization
              Runnable createEDT = new Runnable() {
                public void run() {
                }

                ;
              };
              eventQueue.postEvent(new InvocationEvent(this, createEDT));
              EventDispatchThread edt = eventQueue.getDispatchThread();
              edt.addEventFilter(modalFilter);
            }
          }

          modalityPushed();
          try {
            final EventQueue eventQueue = AccessController.doPrivileged(
                new PrivilegedAction<EventQueue>() {
                  public EventQueue run() {
                    return Toolkit.getDefaultToolkit().getSystemEventQueue();
                  }
                });
            secondaryLoop = eventQueue.createSecondaryLoop(cond, modalFilter, 0);
            if (!secondaryLoop.enter()) {
              secondaryLoop = null;
            }
          } finally {
            modalityPopped();
          }

          // if this dialog is toolkit-modal, its filter must be removed
          // from all EDTs (for all AppContexts)
          if (modalityType == ModalityType.TOOLKIT_MODAL) {
            Iterator<AppContext> it = AppContext.getAppContexts().iterator();
            while (it.hasNext()) {
              AppContext appContext = it.next();
              if (appContext == showAppContext) {
                continue;
              }
              EventQueue eventQueue = (EventQueue) appContext.get(AppContext.EVENT_QUEUE_KEY);
              EventDispatchThread edt = eventQueue.getDispatchThread();
              edt.removeEventFilter(modalFilter);
            }
          }

          if (windowClosingException != null) {
            windowClosingException.fillInStackTrace();
            throw windowClosingException;
          }
        }
      } finally {
        if (predictedFocusOwner != null) {
          // Restore normal key event dispatching
          KeyboardFocusManager.getCurrentKeyboardFocusManager().
              dequeueKeyEvents(time.get(), predictedFocusOwner);
        }
      }
    }
  }

  final void modalityPushed() {
    Toolkit tk = Toolkit.getDefaultToolkit();
    if (tk instanceof SunToolkit) {
      SunToolkit stk = (SunToolkit) tk;
      stk.notifyModalityPushed(this);
    }
  }

  final void modalityPopped() {
    Toolkit tk = Toolkit.getDefaultToolkit();
    if (tk instanceof SunToolkit) {
      SunToolkit stk = (SunToolkit) tk;
      stk.notifyModalityPopped(this);
    }
  }

  void interruptBlocking() {
    if (isModal()) {
      disposeImpl();
    } else if (windowClosingException != null) {
      windowClosingException.fillInStackTrace();
      windowClosingException.printStackTrace();
      windowClosingException = null;
    }
  }

  private void hideAndDisposePreHandler() {
    isInHide = true;
    synchronized (getTreeLock()) {
      if (secondaryLoop != null) {
        modalHide();
        // dialog can be shown and then disposed before its
        // modal filter is created
        if (modalFilter != null) {
          modalFilter.disable();
        }
        modalDialogs.remove(this);
      }
    }
  }

  private void hideAndDisposeHandler() {
    if (secondaryLoop != null) {
      secondaryLoop.exit();
      secondaryLoop = null;
    }
    isInHide = false;
  }

  /**
   * Hides the Dialog and then causes {@code show} to return if it is currently
   * blocked.
   *
   * @see Window#show
   * @see Window#dispose
   * @see Window#setVisible(boolean)
   * @deprecated As of JDK version 1.5, replaced by {@link #setVisible(boolean)
   * setVisible(boolean)}.
   */
  @Deprecated
  public void hide() {
    hideAndDisposePreHandler();
    super.hide();
    // fix for 5048370: if hide() is called from super.doDispose(), then
    // hideAndDisposeHandler() should not be called here as it will be called
    // at the end of doDispose()
    if (!isInDispose) {
      hideAndDisposeHandler();
    }
  }

  /**
   * Disposes the Dialog and then causes show() to return if it is currently
   * blocked.
   */
  void doDispose() {
    // fix for 5048370: set isInDispose flag to true to prevent calling
    // to hideAndDisposeHandler() from hide()
    isInDispose = true;
    super.doDispose();
    hideAndDisposeHandler();
    isInDispose = false;
  }

  /**
   * {@inheritDoc}
   * <p>
   * If this dialog is modal and blocks some windows, then all of them are
   * also sent to the back to keep them below the blocking dialog.
   *
   * @see java.awt.Window#toBack
   */
  public void toBack() {
    super.toBack();
    if (visible) {
      synchronized (getTreeLock()) {
        for (Window w : blockedWindows) {
          w.toBack_NoClientCode();
        }
      }
    }
  }

  /**
   * Indicates whether this dialog is resizable by the user.
   * By default, all dialogs are initially resizable.
   *
   * @return <code>true</code> if the user can resize the dialog; <code>false</code> otherwise.
   * @see java.awt.Dialog#setResizable
   */
  public boolean isResizable() {
    return resizable;
  }

  /**
   * Sets whether this dialog is resizable by the user.
   *
   * @param resizable <code>true</code> if the user can resize this dialog; <code>false</code>
   * otherwise.
   * @see java.awt.Dialog#isResizable
   */
  public void setResizable(boolean resizable) {
    boolean testvalid = false;

    synchronized (this) {
      this.resizable = resizable;
      DialogPeer peer = (DialogPeer) this.peer;
      if (peer != null) {
        peer.setResizable(resizable);
        testvalid = true;
      }
    }

    // On some platforms, changing the resizable state affects
    // the insets of the Dialog. If we could, we'd call invalidate()
    // from the peer, but we need to guarantee that we're not holding
    // the Dialog lock when we call invalidate().
    if (testvalid) {
      invalidateIfValid();
    }
  }


  /**
   * Disables or enables decorations for this dialog.
   * <p>
   * This method can only be called while the dialog is not displayable. To
   * make this dialog decorated, it must be opaque and have the default shape,
   * otherwise the {@code IllegalComponentStateException} will be thrown.
   * Refer to {@link Window#setShape}, {@link Window#setOpacity} and {@link
   * Window#setBackground} for details
   *
   * @param undecorated {@code true} if no dialog decorations are to be enabled; {@code false} if
   * dialog decorations are to be enabled
   * @throws IllegalComponentStateException if the dialog is displayable
   * @throws IllegalComponentStateException if {@code undecorated} is {@code false}, and this dialog
   * does not have the default shape
   * @throws IllegalComponentStateException if {@code undecorated} is {@code false}, and this dialog
   * opacity is less than {@code 1.0f}
   * @throws IllegalComponentStateException if {@code undecorated} is {@code false}, and the alpha
   * value of this dialog background color is less than {@code 1.0f}
   * @see #isUndecorated
   * @see Component#isDisplayable
   * @see Window#getShape
   * @see Window#getOpacity
   * @see Window#getBackground
   * @since 1.4
   */
  public void setUndecorated(boolean undecorated) {
        /* Make sure we don't run in the middle of peer creation.*/
    synchronized (getTreeLock()) {
      if (isDisplayable()) {
        throw new IllegalComponentStateException("The dialog is displayable.");
      }
      if (!undecorated) {
        if (getOpacity() < 1.0f) {
          throw new IllegalComponentStateException("The dialog is not opaque");
        }
        if (getShape() != null) {
          throw new IllegalComponentStateException("The dialog does not have a default shape");
        }
        Color bg = getBackground();
        if ((bg != null) && (bg.getAlpha() < 255)) {
          throw new IllegalComponentStateException("The dialog background color is not opaque");
        }
      }
      this.undecorated = undecorated;
    }
  }

  /**
   * Indicates whether this dialog is undecorated.
   * By default, all dialogs are initially decorated.
   *
   * @return <code>true</code> if dialog is undecorated; <code>false</code> otherwise.
   * @see java.awt.Dialog#setUndecorated
   * @since 1.4
   */
  public boolean isUndecorated() {
    return undecorated;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void setOpacity(float opacity) {
    synchronized (getTreeLock()) {
      if ((opacity < 1.0f) && !isUndecorated()) {
        throw new IllegalComponentStateException("The dialog is decorated");
      }
      super.setOpacity(opacity);
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void setShape(Shape shape) {
    synchronized (getTreeLock()) {
      if ((shape != null) && !isUndecorated()) {
        throw new IllegalComponentStateException("The dialog is decorated");
      }
      super.setShape(shape);
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void setBackground(Color bgColor) {
    synchronized (getTreeLock()) {
      if ((bgColor != null) && (bgColor.getAlpha() < 255) && !isUndecorated()) {
        throw new IllegalComponentStateException("The dialog is decorated");
      }
      super.setBackground(bgColor);
    }
  }

  /**
   * Returns a string representing the state of this dialog. This
   * method is intended to be used only for debugging purposes, and the
   * content and format of the returned string may vary between
   * implementations. The returned string may be empty but may not be
   * <code>null</code>.
   *
   * @return the parameter string of this dialog window.
   */
  protected String paramString() {
    String str = super.paramString() + "," + modalityType;
    if (title != null) {
      str += ",title=" + title;
    }
    return str;
  }

  /**
   * Initialize JNI field and method IDs
   */
  private static native void initIDs();

    /*
     * --- Modality support ---
     *
     */

  /*
   * This method is called only for modal dialogs.
   *
   * Goes through the list of all visible top-level windows and
   * divide them into three distinct groups: blockers of this dialog,
   * blocked by this dialog and all others. Then blocks this dialog
   * by first met dialog from the first group (if any) and blocks all
   * the windows from the second group.
   */
  void modalShow() {
    // find all the dialogs that block this one
    IdentityArrayList<Dialog> blockers = new IdentityArrayList<Dialog>();
    for (Dialog d : modalDialogs) {
      if (d.shouldBlock(this)) {
        Window w = d;
        while ((w != null) && (w != this)) {
          w = w.getOwner_NoClientCode();
        }
        if ((w == this) || !shouldBlock(d) || (modalityType.compareTo(d.getModalityType()) < 0)) {
          blockers.add(d);
        }
      }
    }

    // add all blockers' blockers to blockers :)
    for (int i = 0; i < blockers.size(); i++) {
      Dialog blocker = blockers.get(i);
      if (blocker.isModalBlocked()) {
        Dialog blockerBlocker = blocker.getModalBlocker();
        if (!blockers.contains(blockerBlocker)) {
          blockers.add(i + 1, blockerBlocker);
        }
      }
    }

    if (blockers.size() > 0) {
      blockers.get(0).blockWindow(this);
    }

    // find all windows from blockers' hierarchies
    IdentityArrayList<Window> blockersHierarchies = new IdentityArrayList<Window>(blockers);
    int k = 0;
    while (k < blockersHierarchies.size()) {
      Window w = blockersHierarchies.get(k);
      Window[] ownedWindows = w.getOwnedWindows_NoClientCode();
      for (Window win : ownedWindows) {
        blockersHierarchies.add(win);
      }
      k++;
    }

    java.util.List<Window> toBlock = new IdentityLinkedList<Window>();
    // block all windows from scope of blocking except from blockers' hierarchies
    IdentityArrayList<Window> unblockedWindows = Window.getAllUnblockedWindows();
    for (Window w : unblockedWindows) {
      if (shouldBlock(w) && !blockersHierarchies.contains(w)) {
        if ((w instanceof Dialog) && ((Dialog) w).isModal_NoClientCode()) {
          Dialog wd = (Dialog) w;
          if (wd.shouldBlock(this) && (modalDialogs.indexOf(wd) > modalDialogs.indexOf(this))) {
            continue;
          }
        }
        toBlock.add(w);
      }
    }
    blockWindows(toBlock);

    if (!isModalBlocked()) {
      updateChildrenBlocking();
    }
  }

  /*
   * This method is called only for modal dialogs.
   *
   * Unblocks all the windows blocked by this modal dialog. After
   * each of them has been unblocked, it is checked to be blocked by
   * any other modal dialogs.
   */
  void modalHide() {
    // we should unblock all the windows first...
    IdentityArrayList<Window> save = new IdentityArrayList<Window>();
    int blockedWindowsCount = blockedWindows.size();
    for (int i = 0; i < blockedWindowsCount; i++) {
      Window w = blockedWindows.get(0);
      save.add(w);
      unblockWindow(w); // also removes w from blockedWindows
    }
    // ... and only after that check if they should be blocked
    // by another dialogs
    for (int i = 0; i < blockedWindowsCount; i++) {
      Window w = save.get(i);
      if ((w instanceof Dialog) && ((Dialog) w).isModal_NoClientCode()) {
        Dialog d = (Dialog) w;
        d.modalShow();
      } else {
        checkShouldBeBlocked(w);
      }
    }
  }

  /*
   * Returns whether the given top-level window should be blocked by
   * this dialog. Note, that the given window can be also a modal dialog
   * and it should block this dialog, but this method do not take such
   * situations into consideration (such checks are performed in the
   * modalShow() and modalHide() methods).
   *
   * This method should be called on the getTreeLock() lock.
   */
  boolean shouldBlock(Window w) {
    if (!isVisible_NoClientCode() ||
        (!w.isVisible_NoClientCode() && !w.isInShow) ||
        isInHide ||
        (w == this) ||
        !isModal_NoClientCode()) {
      return false;
    }
    if ((w instanceof Dialog) && ((Dialog) w).isInHide) {
      return false;
    }
    // check if w is from children hierarchy
    // fix for 6271546: we should also take into consideration child hierarchies
    // of this dialog's blockers
    Window blockerToCheck = this;
    while (blockerToCheck != null) {
      Component c = w;
      while ((c != null) && (c != blockerToCheck)) {
        c = c.getParent_NoClientCode();
      }
      if (c == blockerToCheck) {
        return false;
      }
      blockerToCheck = blockerToCheck.getModalBlocker();
    }
    switch (modalityType) {
      case MODELESS:
        return false;
      case DOCUMENT_MODAL:
        if (w.isModalExcluded(ModalExclusionType.APPLICATION_EXCLUDE)) {
          // application- and toolkit-excluded windows are not blocked by
          // document-modal dialogs from outside their children hierarchy
          Component c = this;
          while ((c != null) && (c != w)) {
            c = c.getParent_NoClientCode();
          }
          return c == w;
        } else {
          return getDocumentRoot() == w.getDocumentRoot();
        }
      case APPLICATION_MODAL:
        return !w.isModalExcluded(ModalExclusionType.APPLICATION_EXCLUDE) &&
            (appContext == w.appContext);
      case TOOLKIT_MODAL:
        return !w.isModalExcluded(ModalExclusionType.TOOLKIT_EXCLUDE);
    }

    return false;
  }

  /*
   * Adds the given top-level window to the list of blocked
   * windows for this dialog and marks it as modal blocked.
   * If the window is already blocked by some modal dialog,
   * does nothing.
   */
  void blockWindow(Window w) {
    if (!w.isModalBlocked()) {
      w.setModalBlocked(this, true, true);
      blockedWindows.add(w);
    }
  }

  void blockWindows(java.util.List<Window> toBlock) {
    DialogPeer dpeer = (DialogPeer) peer;
    if (dpeer == null) {
      return;
    }
    Iterator<Window> it = toBlock.iterator();
    while (it.hasNext()) {
      Window w = it.next();
      if (!w.isModalBlocked()) {
        w.setModalBlocked(this, true, false);
      } else {
        it.remove();
      }
    }
    dpeer.blockWindows(toBlock);
    blockedWindows.addAll(toBlock);
  }

  /*
   * Removes the given top-level window from the list of blocked
   * windows for this dialog and marks it as unblocked. If the
   * window is not modal blocked, does nothing.
   */
  void unblockWindow(Window w) {
    if (w.isModalBlocked() && blockedWindows.contains(w)) {
      blockedWindows.remove(w);
      w.setModalBlocked(this, false, true);
    }
  }

  /*
   * Checks if any other modal dialog D blocks the given window.
   * If such D exists, mark the window as blocked by D.
   */
  static void checkShouldBeBlocked(Window w) {
    synchronized (w.getTreeLock()) {
      for (int i = 0; i < modalDialogs.size(); i++) {
        Dialog modalDialog = modalDialogs.get(i);
        if (modalDialog.shouldBlock(w)) {
          modalDialog.blockWindow(w);
          break;
        }
      }
    }
  }

  private void checkModalityPermission(ModalityType mt) {
    if (mt == ModalityType.TOOLKIT_MODAL) {
      SecurityManager sm = System.getSecurityManager();
      if (sm != null) {
        sm.checkPermission(
            SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION
        );
      }
    }
  }

  private void readObject(ObjectInputStream s)
      throws ClassNotFoundException, IOException, HeadlessException {
    GraphicsEnvironment.checkHeadless();

    java.io.ObjectInputStream.GetField fields =
        s.readFields();

    ModalityType localModalityType = (ModalityType) fields.get("modalityType", null);

    try {
      checkModalityPermission(localModalityType);
    } catch (AccessControlException ace) {
      localModalityType = DEFAULT_MODALITY_TYPE;
    }

    // in 1.5 or earlier modalityType was absent, so use "modal" instead
    if (localModalityType == null) {
      this.modal = fields.get("modal", false);
      setModal(modal);
    } else {
      this.modalityType = localModalityType;
    }

    this.resizable = fields.get("resizable", true);
    this.undecorated = fields.get("undecorated", false);
    this.title = (String) fields.get("title", "");

    blockedWindows = new IdentityArrayList<>();

    SunToolkit.checkAndSetPolicy(this);

    initialized = true;

  }

    /*
     * --- Accessibility Support ---
     *
     */

  /**
   * Gets the AccessibleContext associated with this Dialog.
   * For dialogs, the AccessibleContext takes the form of an
   * AccessibleAWTDialog.
   * A new AccessibleAWTDialog instance is created if necessary.
   *
   * @return an AccessibleAWTDialog that serves as the AccessibleContext of this Dialog
   * @since 1.3
   */
  public AccessibleContext getAccessibleContext() {
    if (accessibleContext == null) {
      accessibleContext = new AccessibleAWTDialog();
    }
    return accessibleContext;
  }

  /**
   * This class implements accessibility support for the
   * <code>Dialog</code> class.  It provides an implementation of the
   * Java Accessibility API appropriate to dialog user-interface elements.
   *
   * @since 1.3
   */
  protected class AccessibleAWTDialog extends AccessibleAWTWindow {

    /*
     * JDK 1.3 serialVersionUID
     */
    private static final long serialVersionUID = 4837230331833941201L;

    /**
     * Get the role of this object.
     *
     * @return an instance of AccessibleRole describing the role of the object
     * @see AccessibleRole
     */
    public AccessibleRole getAccessibleRole() {
      return AccessibleRole.DIALOG;
    }

    /**
     * Get the state of this object.
     *
     * @return an instance of AccessibleStateSet containing the current state set of the object
     * @see AccessibleState
     */
    public AccessibleStateSet getAccessibleStateSet() {
      AccessibleStateSet states = super.getAccessibleStateSet();
      if (getFocusOwner() != null) {
        states.add(AccessibleState.ACTIVE);
      }
      if (isModal()) {
        states.add(AccessibleState.MODAL);
      }
      if (isResizable()) {
        states.add(AccessibleState.RESIZABLE);
      }
      return states;
    }

  } // inner class AccessibleAWTDialog
}
